package com.example.miniofenpian.util;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.CreateBucketRequest;
import com.example.miniofenpian.config.OssConfig;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.Assert;

import javax.annotation.PreDestroy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author fulin
 * @since 2024/9/19 17:49
 */
public class AmazonS3Util {

    // 当前项目中的可用的AmazonS3实例
    private static final Map<String, AmazonS3> AMAZON_S_3_MAP = new ConcurrentHashMap<>();

    private static OssConfig OSS_CONFIG = null;

    public static OssConfig getOssConfig() {
        return OSS_CONFIG;
    }

    /**
     * 初始化AmazonS3
     */
    public static AmazonS3 initAmazonS3() {
        StringRedisTemplate redisTemplate = SpringUtil.getBean(StringRedisTemplate.class);
        // 获取redis 默认类型
        String configKey = redisTemplate.opsForValue().get(Constant.OSS_CONFIG_KEY);
        Assert.hasText(configKey, "未配置默认存储类型");
        String configJson = redisTemplate.opsForValue().get(Constant.OSS_CONFIG_PROPERTIES + StrUtil.COLON + configKey);
        Assert.hasText(configJson, "未配置存储类型配置信息");
        OssConfig ossConfig = JSONUtil.toBean(configJson, OssConfig.class);
        AmazonS3 amazonS3 = AMAZON_S_3_MAP.get(configKey);
        if (ObjectUtil.isNull(amazonS3)) {
            amazonS3 = getAmazonS3(configKey, ossConfig);
            AMAZON_S_3_MAP.put(configKey, amazonS3);
        }
        OSS_CONFIG = ossConfig;
        return amazonS3;
    }

    private static AmazonS3 getAmazonS3(String configKey, OssConfig ossConfig) {
        AwsClientBuilder.EndpointConfiguration endpointConfig =
                new AwsClientBuilder.EndpointConfiguration(ossConfig.getEndpoint(), ossConfig.getRegion());

        AWSCredentials credentials = new BasicAWSCredentials(ossConfig.getAccessKey(), ossConfig.getSecretKey());
        AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);
        ClientConfiguration clientConfig = new ClientConfiguration();
        if ("1".equals(ossConfig.getIsHttps())) {
            clientConfig.setProtocol(Protocol.HTTPS);
        } else {
            clientConfig.setProtocol(Protocol.HTTP);
        }
        AmazonS3ClientBuilder build = AmazonS3Client.builder()
                .withEndpointConfiguration(endpointConfig)
                .withClientConfiguration(clientConfig)
                .withCredentials(credentialsProvider)
                .disableChunkedEncoding();
        // minio 使用https限制使用域名访问 需要此配置 站点填域名
        build.enablePathStyleAccess();
        AmazonS3 amazonS3 = build.build();
        if (!Constant.OSSType.LOCAL.name().equalsIgnoreCase(configKey)) {
            String bucketName = ossConfig.getBucketName();
            if (!amazonS3.doesBucketExistV2(bucketName)) {
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                createBucketRequest.withCannedAcl(CannedAccessControlList.PublicRead);
                amazonS3.createBucket(createBucketRequest);
                // 手动设置桶为public
            }
        }
        return amazonS3;
    }


    @PreDestroy
    public static void clear() {
        AMAZON_S_3_MAP.clear();
    }

}
